package com.conversationboard.database;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;

import com.conversationboard.config.Configuration;
import com.conversationboard.config.ConnectionStrategy;
import com.conversationboard.site.Site;

/** Simple class with a static method to wrapper requests to get a database connection. This class will change
 * in time to pick up a connection from a Tomcat connection pool (or whatever container it lives in. For now,
 * for test purposes, it just creates new connections. This is expensive and shouldn't be used in a production
 * environment.
 * 
 * @author Keith Watson */

public class Database {

	/** Make a connection to the MySql instance, and to the ILX2 database, within that instance. Note that
	 * DriverManager.getConnection is already synchronized, so this class is already threadsafe. If you are
	 * using connection pooling (set the static boolean), you'll have to have the connection pool properly set
	 * up in Tomcat.
	 * 
	 * @return a java.sql.Connection implementation
	 * @throws ClassNotFoundException
	 * @throws SQLException */

	static {

		try {
			Class.forName("com.mysql.jdbc.Driver");
		} catch (ClassNotFoundException e) {
			throw new RuntimeException("Couldn't find the MySql JDBC driver. Failed the Class.forName load in Database.getConnection");
		}

	}

	public static Connection staticConnection = null;
	public static String url = "jdbc:mysql://localhost:3306/ilxtest";
	public static String datasourceJndiName = null;


	public static Connection getConnection() throws SQLException {

		Connection connection = null;

		if (Configuration.getInstance().getConnectionStrategy() == ConnectionStrategy.GenerateConnection) {

			connection = DriverManager.getConnection(url, "root", "");

			return connection;

		} else if (Configuration.getInstance().getConnectionStrategy() == ConnectionStrategy.StaticConnection) {

			if (staticConnection != null) {
				return staticConnection;
			}

			connection = DriverManager.getConnection(url, "root", "");

			staticConnection = connection;
			return staticConnection;

		} else if (Configuration.getInstance().getConnectionStrategy() == ConnectionStrategy.ConnectionPooling) {

			try {

				Context context = new InitialContext();
				Context environmentContext = (Context) context.lookup("java:comp/env");
				DataSource dataSource = (DataSource) environmentContext.lookup("jdbc/ilxDataSource");

				if (dataSource != null) {
					connection = dataSource.getConnection();

					if (Configuration.getInstance().isStoreDatabaseConnectionInfo()) {

						ConnectionWrapper connectionWrapper = new ConnectionWrapper(connection);

						Throwable throwable = new Throwable();
						StackTraceElement[] elements = throwable.getStackTrace();

						String callerMethodName = elements[1].getMethodName();

						if (callerMethodName == null || callerMethodName.trim().equals("")) {
							callerMethodName = "[Static Initialiser]";
						}

						String callerClassName = elements[1].getClassName();

						String record = callerClassName + "." + callerMethodName + "()";

						connectionWrapper.setCallerName(record);
						connectionWrapper.setTime(System.nanoTime());

						return connectionWrapper;
					}

				}

			} catch (Throwable t) {
				t.printStackTrace();
			}

			return connection;

		}

		throw new RuntimeException("No such connection strategy");

	}


	public static void close(Connection connection) throws SQLException {

		if (connection != null && !(Configuration.getInstance().getConnectionStrategy() == ConnectionStrategy.StaticConnection)) {

			if (Configuration.getInstance().isStoreDatabaseConnectionInfo()) {
				ConnectionWrapper connectionWrapper = (ConnectionWrapper) connection;

				/* Record time in microseconds */
				long time = ((System.nanoTime() - connectionWrapper.getTime()) / 1000);
				String callerName = connectionWrapper.getCallerName();

				Site.recordDatabaseConnectionInfo(callerName, time);
			}

			connection.close();
		}
	}
}
